//
// Created by wxd on 2025/8/15.
//

#include "Plane.h"

// 这里的mesh思路：通过外积构建平面的局部坐标系，然后在计算平面在这个局部坐标系下的顶点坐标
// 我们约定我们计算顶点的顺序：逆时针
void Plane::raster() {
    if (m_Width <= 0.f || m_Height <= 0.f) return;

    if (m_Normal.y < 0.f) {
        m_Normal.y = -m_Normal.y; // 如果是内法，转化为外法
    }

    m_Normal = glm::normalize(m_Normal);

    const auto halfW = m_Width / 2.f;
    const auto halfH = m_Height / 2.f;

    glm::vec3 v1;
    glm::vec3 v2;
    glm::vec3 v3;
    glm::vec3 v4;


    // 判断当前外法向量是否和OpenGL坐标系的y轴的单位向量重叠
    if (m_Normal == m_OrthoBase.ey) {
        v1 = glm::vec3(-halfW, 0.f,halfH) + m_Center;
        v2 = glm::vec3(halfW, 0.f, halfH) + m_Center;
        v3 = glm::vec3(halfW, 0.f, -halfH) + m_Center;
        v4 = glm::vec3(-halfW, 0.f, -halfH) + m_Center;
    } else {
        // 构建平面以平面中心为原点的局部坐标系， 这个局部坐标系的y轴就是平面的外法向量(已经单位化过)
        const glm::vec3 locZ = glm::cross(m_Normal, m_OrthoBase.ey);
        const glm::vec3 locX = glm::cross(m_Normal, locZ);

        // 此时我们构建平面以中心为原点的局部坐标系 {locX, mNormal, locZ}
        v1 = m_Center - halfW * locX + halfH * locZ;
        v2 = m_Center + halfW * locX + halfH * locZ;
        v3 = m_Center + halfW * locX - halfH * locZ;
        v4 = m_Center - halfW * locX - halfH * locZ;
    }

    m_PlaneVertices.push_back(v1);
    m_PlaneVertices.push_back(v2);
    m_PlaneVertices.push_back(v3);
    m_PlaneVertices.push_back(v4);

    m_PlaneNormals.push_back(m_Normal);
    m_PlaneNormals.push_back(m_Normal);
    m_PlaneNormals.push_back(m_Normal);
    m_PlaneNormals.push_back(m_Normal);

    m_PlaneFaces.push_back(glm::uvec3(0, 1, 2));
    m_PlaneFaces.push_back(glm::uvec3(0, 2, 3));
    std::vector<unsigned int> indices;
    indices.push_back(0);
    indices.push_back(1);
    indices.push_back(2);
    indices.push_back(0);
    indices.push_back(2);
    indices.push_back(3);

    m_PlaneTexCoords.push_back(glm::vec2(0.f));
    m_PlaneTexCoords.push_back(glm::vec2(1.f, 0.f));
    m_PlaneTexCoords.push_back(glm::vec2(1.f, 1.f));
    m_PlaneTexCoords.push_back(glm::vec2(0.f, 1.f));

    getVAO()->bind();
    BaseGeometry::initEBO(indices, GL_STATIC_DRAW);
    BaseGeometry::setPos(0, m_PlaneVertices);
    BaseGeometry::setUV(2, m_PlaneTexCoords);
    BaseGeometry::setNormal(3, m_PlaneNormals);
    getVAO()->unbind();
}

